﻿using System;
using System.Collections.Generic;
using System.Linq;
using InvestmentIntelligence.Data.Repository.Comparers.EntityModelsComparers;
using InvestmentIntelligence.DbModel.Models;
using InvestmentIntelligence.Extensions;

namespace InvestmentIntelligence.Data.Repository.EFImplementation
{
    public class EconomicSectorRepository : IIPRepository<EconomicSector>, IEconomicSectorUpdatableRepository
    {
        private static readonly Lazy<Dictionary<int, EconomicSector>> EconomicSectorsMap =
            new Lazy<Dictionary<int, EconomicSector>>(GetEconomicSectorsMap);

        private static Dictionary<int, EconomicSector> GetEconomicSectorsMap()
        {
            return (new EconomicSectorRepository()).GetList().ToDictionaryFast(k => k.Id);
        }

        public static string GetItemDescription(int id)
        {
            return EconomicSectorsMap.Value[id].Description;
        }

        public static int GetItemRootId(int id)
        {
            var sectorMap = EconomicSectorsMap.Value;
            var sector = sectorMap[id];

            while (sector.ParentId.HasValue)
            {
                sector = sectorMap[sector.ParentId.Value];
            }

            return sector.Id;
        }

        public static string GetItemsRootDescription(int id)
        {
            int rootId = GetItemRootId(id);
            return GetItemDescription(rootId);
        }

        public EconomicSector Get(int id)
        {
            return Get(v => v.Id == id);
        }

        public new int Add(EconomicSector item)
        {
            var sector = new EconomicSector
            {
                SectorId = item.SectorId,
                Description = item.Description.Trim(),
                ParentId = item.ParentId,
            };

            base.Add(sector);
            return sector.Id;
        }

        public int Add(int sectorId, string description, int? parentId)
        {
            var sector = new EconomicSector
            {
                SectorId = sectorId,
                Description = string.IsNullOrWhiteSpace(description) ? string.Empty : description.Trim(),
                ParentId = parentId,
            };

            base.Add(sector);
            return sector.Id;
        }

        public new void Update(EconomicSector item)
        {
            var actualSector = Get(item.Id);

            if (actualSector == null)
            {
                throw new NullReferenceException("sector no exist");
            }

            actualSector.SectorId = item.SectorId;
            actualSector.Description = item.Description.Trim();
            actualSector.ParentId = item.ParentId;
            base.Update(actualSector);
        }

        [Obsolete("Pay attention to parent-child relationships. Please, Use Add() method instead.")]
        public List<EconomicSector> SaveNew(IEnumerable<EconomicSector> items)
        {
            var sectors = GetList();
            var newSectors = items.Except(sectors, new EconomicSectorCodeComparer());
            Add(newSectors);
            return GetList();
        }

        public Dictionary<int, List<EconomicSector>> GetDictionary()
        {
            // in normal way every list will have 1 item
            // this will change if smbdy will add Econ. Sect. with wrong SectorId
            var result = GetList().GroupBy(k => k.SectorId).ToDictionary(k => k.Key, items => items.ToList());
            return result;
        }
    }
}